/*************************************************************************
    > File Name: threadpool.h
    > Author: 侯广臣
    > Mail: 2801059691@qq.com 
    > Created Time: 2020年12月27日 星期日 08时59分12秒
 ************************************************************************/

#ifndef _THREADPOOL_H_
#define _THREADPOOL_H_

#include <stdlib.h>
#include <pthread.h>

template<typename ReturnType, typename ArgType>
class CThreadInfo
{
	public:
		//定义回调函数类型变量
		typedef ReturnType(* ThreadWorking)(ArgType);
	private:
		bool			m_loopRunThread;	//判断是否循环执行线程
		ReturnType		m_returnValue;		//保存当前线程的返回值
		ArgType			m_argValue;			//保存当前线程的参数值
		ThreadWorking	m_worker;			//保存线程内执行用户任务的函数
		pthread_t		m_threadID;			//保存当前线程的ID
		pthread_mutex_t	m_threadBlockLock;	//用于阻塞线程运行的互斥锁
		pthread_mutex_t	m_threadStateLock;	//用于显示当前线程运行状态的互斥锁

		//此函数作为创建线程的函数，在函数内部执行用户所提供函数
		static void* ThreadMain(void *arg)
		{
			CThreadInfo *p = (CThreadInfo*)arg;
			while(p->m_loopRunThread)
			{
				printf("这是%ld线程\n", p->m_threadID);
				pthread_mutex_lock(&(p->m_threadBlockLock));
				//执行用户函数
				p->m_returnValue = (*(p->m_worker))(p->m_argValue);
				pthread_mutex_unlock(&(p->m_threadStateLock));
			}
			return NULL;
		}

	public:
		CThreadInfo(ThreadWorking worker = NULL, bool loopRunThread = true)
			: m_loopRunThread(loopRunThread)
		{
			pthread_mutex_init(&m_threadBlockLock, NULL);
			pthread_mutex_lock(&m_threadBlockLock);
			pthread_mutex_init(&m_threadStateLock, NULL);
			if(worker != NULL)
			{
				m_worker = worker;
				pthread_create(&m_threadID, NULL, ThreadMain, NULL);
			}
			//pthread_detach(m_threadID);
		}

		//初始化线程
		void Init(ThreadWorking worker, bool loopRunThread = true)
		{
			m_worker = worker;
			m_loopRunThread = loopRunThread;
			pthread_create(&m_threadID, NULL, ThreadMain, this);
			pthread_detach(m_threadID);
		}

		~CThreadInfo()
		{
			m_loopRunThread = false;
			//pthread_join(m_threadID, NULL);
			pthread_mutex_destroy(&m_threadBlockLock);
			pthread_mutex_destroy(&m_threadStateLock);
		}

		int TryLock()
		{
			return pthread_mutex_trylock(&m_threadStateLock);
		}
		int SetArg(ArgType arg)
		{
			m_argValue = arg;
			return pthread_mutex_unlock(&m_threadBlockLock);
		}

		ReturnType GetReturnValue(void)
		{
			return m_returnValue;
		}
		pthread_t GetThreadID(void)
		{
			return m_threadID;
		}
};


template<typename ReturnType, typename ArgType>
class CThreadPool
{
	private:
		CThreadInfo<ReturnType, ArgType> *m_threadPool;	//线程类数组，线程池
		int m_threadNumber;			//线程池内线程数量
		int m_lastTimeWorkerIndex;	//上次选中的工作线程
	public:
		CThreadPool(ReturnType (*WorkerFunction)(ArgType), const int threadNumber)
			: m_threadNumber(threadNumber), m_lastTimeWorkerIndex(0)
		{
			//分配线程池内存
			m_threadPool = new CThreadInfo<int, int>[m_threadNumber];
			//初始化并运行线程
			for(int i = 0; i < m_threadNumber; i++)
			{
				m_threadPool[i].Init(WorkerFunction);
			}
		}

		~CThreadPool()
		{
			delete[] m_threadPool;
		}
		//发布任务，如果所有线程忙返回 -1
		int ReleaseTask(ArgType data) 
		{
			//以上次选中的工作线程的下一个线程为起始查找空闲线程
			int index = m_lastTimeWorkerIndex;
			do{
				++index;
				//循环查找
				index %= m_threadNumber;
				//成功找到空闲线程填充数据，启动线程
				if(m_threadPool[index].TryLock() == 0)
				{
					m_threadPool[index].SetArg(data);
					m_lastTimeWorkerIndex = index;
					return index;
				}
			}while(index != m_lastTimeWorkerIndex);
			//没有找到返回-1
			return -1;
		}

};


#endif
